package cn.wolfcode.wolf2w.business.service.impl;

import cn.wolfcode.wolf2w.business.api.RemoteDestinationService;
import cn.wolfcode.wolf2w.business.api.RemoteNoteService;
import cn.wolfcode.wolf2w.business.api.RemoteStrategyService;
import cn.wolfcode.wolf2w.business.api.domain.*;
import cn.wolfcode.wolf2w.business.query.SearchQuery;
import cn.wolfcode.wolf2w.business.repository.DestinationEsRepository;
import cn.wolfcode.wolf2w.business.repository.NoteEsRepository;
import cn.wolfcode.wolf2w.business.repository.StrategyEsRepository;
import cn.wolfcode.wolf2w.business.repository.UserEsRepository;
import cn.wolfcode.wolf2w.business.service.ISearchService;
import cn.wolfcode.wolf2w.common.core.constant.SecurityConstants;
import cn.wolfcode.wolf2w.member.api.RemoteUserInfoService;
import cn.wolfcode.wolf2w.member.api.domain.UserInfo;
import cn.wolfcode.wolf2w.system.api.RemoteUserService;
import org.apache.commons.beanutils.BeanUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class SearchServiceImpl implements ISearchService {

    @Autowired
    private StrategyEsRepository strategyEsRepository;
    @Autowired
    private NoteEsRepository noteEsRepository;
    //用于执行高亮等复杂查询
    @Autowired
    private ElasticsearchRestTemplate template;

    @Autowired
    private RemoteStrategyService remoteStrategyService;
    @Autowired
    private RemoteNoteService remoteNoteService;
    @Autowired
    private UserEsRepository userEsRepository;
    @Autowired
    private RemoteUserInfoService remoteUserInfoService;
    @Autowired
    private DestinationEsRepository destinationEsRepository;
    @Autowired
    private RemoteDestinationService remoteDestinationService;

    @Override
    public void saveStrategy(StrategyEs strategyEs) {
        strategyEsRepository.save(strategyEs);
    }

    @Override
    public <T> Page<T> searchWithHighLight(Class<T> clazz, Class<?> esClass, SearchQuery qo, String... fields) throws InvocationTargetException, IllegalAccessException {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(
                QueryBuilders.multiMatchQuery(qo.getKeyword(), fields)
        );
        //高亮
        List<HighlightBuilder.Field> fs = new ArrayList<>();
        for (String field : fields) {
            HighlightBuilder.Field f = new HighlightBuilder.Field(field);
            f.preTags("<span style='color:red'>").postTags("</span>");
            fs.add(f);
        }
        builder.withHighlightFields(fs);

        //设置分页条件
        Pageable pageable= PageRequest.of(qo.getCurrentPage()-1, qo.getPageSize());
        builder.withPageable(pageable);

        //执行查询
        List<T> list=new ArrayList<>();
        SearchHits<?> search = template.search(builder.build(), esClass);
        long totalCount = search.getTotalHits();
        for (SearchHit<?> searchHit : search.getSearchHits()) {
            Long id = Long.valueOf(searchHit.getId());
            T t=null;  //用于存储mysql中的对象
            if (clazz== Strategy.class){
                t= (T) remoteStrategyService.getOne(id, SecurityConstants.INNER).getData();
            } else if(clazz== Note.class){
                t= (T) remoteNoteService.getOne(id, SecurityConstants.INNER).getData();
            }else if (clazz== UserInfo.class){
                t= (T) remoteUserInfoService.getOne(id, SecurityConstants.INNER).getData();
            }else if (clazz== Destination.class){
                t= (T) remoteDestinationService.getOne(id, SecurityConstants.INNER).getData();
            }
            list.add(t);
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            for (String key : highlightFields.keySet()) {//title subtitle content
                List<String> arr = highlightFields.get(key);//<>广州<>最好
                StringBuffer sb = new StringBuffer();
                for (String s : arr) {
                    sb.append(s).append(" ");
                }
                String value=sb.toString();
                BeanUtils.setProperty(t, key, value);
            }
        }
        return new PageImpl<>(list, pageable, totalCount);
    }

    @Override
    public void saveNote(NoteEs noteEs) {
        noteEsRepository.save(noteEs);
    }

    @Override
    public void saveUser(UserEs userEs) {
        userEsRepository.save(userEs);
    }

    @Override
    public void saveDestination(DestinationEs destinationEs) {
        destinationEsRepository.save(destinationEs);
    }

}
